package com.yutian.socketbio.server;

import com.yutian.socketbio.utils.ThreadPoolUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 更复杂的例子， 见 https://www.jianshu.com/p/1db96d04c235
 * @author zhoulei7
 * @create 2020-09-14
 **/
public class CommonServer {
    private static Logger log = LoggerFactory.getLogger(CommonServer.class);

    public static void listen(int port) {
        ThreadPoolExecutor executor = ThreadPoolUtil.createTaskExecutor("CommonServer");
        ServerSocket ss = null;
        try {
            ss = new ServerSocket(port);
            log.info("启动服务器CommonServer，该服务将并行地处理客户端的TCP连接请求，每个连接分配一个处理线程");
            int i = 0;
            while(true) {
                i++;
                // log.info("接受第[" + i + "]个客户端的请求");
                // final int idx = i;
                final Socket s = ss.accept();
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            acceptAndReply(s);
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        }
                        // log.info("处理完第[" + idx + "]个客户端的请求");
                    }
                });

            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);

        } finally {
            // ServerSocket关闭之后，自然和它相关的输入输出流都会被它关闭
            if(null != ss){
                try {
                    ss.close();
                } catch (IOException e) {
                }
            }
        }
    }

    private static void acceptAndReply(Socket s) {
        try {
            log.info("客户端:"+s.getInetAddress().getLocalHost()+"已连接到服务器SimpleServer");

            BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            //读取客户端发送来的消息
            //注：这里读取一行就断开。但实际处理中，会继续等待读取更多客户端消息。
            //br.readLine()在读取客户端发送过来的消息时，由于客户端断线，而其操作系统的不同，
            //这里读取的结果不同：
            //当windows的客户端断开时，br.readLine会抛出异常
            //当linux的客户端断开时，br.readLine会返回null
            String mess = br.readLine();
            log.info("客户端发来消息："+mess);

            try {
                // 模拟业务逻辑时长，创造阻塞条件
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            bw.write(mess+"\n");
            log.info("服务端原文回复消息："+mess);
            bw.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // Socket关闭之后，自然和它相关的输入输出流都会被它关闭
            if(null != s){
                try {
                    s.close();
                    log.info("服务端断开客户端连接");
                } catch (IOException e) {
                }
            }
        }
    }
}
